package network

import (
	"runtime/debug"

	"gitee.com/terender/sfw/rlog"
)

// Proc 游戏处理方法
type Proc func(*Context)

// Party 消息协议组
type Party struct {
	name        string
	s           *Server
	middleWares []Proc
	routines    map[int32]Routine
}

// Use 消息协议组使用一个处理函数作为中间件
// 中间件按照注册的顺序，在消息真正处理函数处理之前被调用
// 任一中间件函数可以终止消息的处理路径，比如验证用户身份失败
func (p *Party) Use(middleware Proc) {
	p.middleWares = append(p.middleWares, middleware)
}

// RegisterProc 注册消息处理路由
func (p *Party) RegisterProc(id int32, proc Proc) {
	r, ok := p.routines[id]
	if ok {
		rlog.Warnf(`RegisterProc to Party[%v] message id[%v] already exists: %+v`, p.name, id, r)
	}
	r = Routine{p: p, proc: proc}
	p.routines[id] = r
	p.s.routines[id] = r
}

// Routine 协议处理路径
type Routine struct {
	p    *Party
	proc Proc
}

// processMessage 沿着协议处理路径处理消息。
// 如果任何一个中间件函数返回后，设置 Context.done 为 true，则处理结束，不再继续执行
func (r *Routine) processMessage(ctx *Context) {
	defer func() {
		if err := recover(); err != nil {
			rlog.Errorf("%+v", err)
			rlog.Rawf(string(debug.Stack()))
		}
	}()
	if ctx.Message().MsgHead.ReqID == 0 {
		rlog.Errorf(`Request message from client must have a non-zero request id`)
	}
	if r.p.s.OnRecvMessage != nil {
		r.p.s.OnRecvMessage(ctx)
	}
	if r.p != nil && len(r.p.middleWares) > 0 {
		ctx.middlewareIndex = 0
		r.p.middleWares[0](ctx)
	} else {
		ctx.middlewareIndex = -1
		r.proc(ctx)
	}
	if !ctx.hasResonsed {
		ctx.Write()
	}
}
